import { useEffect, useState } from 'react'
import dayjs from 'dayjs'
import { Button, Drawer, Form, message, Space, Typography } from 'antd'

import { apiGetEventList } from '@oBiz/components/EventSelect/api'
import { useAddressList } from '@oBiz/hooks/SWRApi/useAddressList'
import {
  apiBatchSetFirstLegInformation,
  apiBatchSetLastLegInformation,
  apiBatchSetLogisticsChannel,
  apiBatchSetPublishEvent,
  apiWaybillRecordAddressInfo,
} from '../../apis'
import {
  FirstLegInformationSetIDTO,
  IBatchSetRes,
  LastMileSetIDTO,
  LogisticChannelSetIDTO,
  PublishPathIDTO,
} from '../../interface'
import { useBoundStore } from '../../store'
import { popupSlot } from '../../utils'
import { AddEvent } from './AddEvent'
import { BatchAction } from './BatchAction'
import { BatchUpdateTable } from './BatchUpdateTable'
import { operationTypeTitleMap } from './config'
import { IBatchOperationsDrawerProps, IFormValue } from './interface'
import styles from './styles.module.less'

const updatePopup = popupSlot.insert(null)

export const BatchOperationsDrawer = Object.assign(
  ({ operationType, destroy }: IBatchOperationsDrawerProps & { destroy: () => void }) => {
    const { open, onHide, afterOpenChange } = popupSlot.useAntdPopupAnimation(destroy)
    const waybillList = useBoundStore(state => state.waybillList)
    const setWaybillList = useBoundStore(state => state.setWaybillList)
    const setEventList = useBoundStore(state => state.setEventList)
    const [updateCount, setUpdateCount] = useState<IBatchSetRes>()
    const addressList = useAddressList({ addressType: 1 })

    const [form] = Form.useForm<IFormValue>()

    const getEventList = async () => {
      const res = await apiGetEventList()
      setEventList(res)
    }

    const initForm = () => {
      form.setFieldsValue({
        content: waybillList?.map(item => ({
          waybillNo: item.waybillNo,
          currentEdd: item.currentEdd ? dayjs(item.currentEdd) : undefined,
          updateEdd: item.currentEdd ? dayjs(item.currentEdd) : undefined,
        })),
      })
    }

    const setBatchAddress = async (eventTemplate: IFormValue['content'][number]['eventTemplate']) => {
      const publishPathIDTOS = waybillList?.map(item => ({
        waybillNo: item.waybillNo,
        eventTemplateId: Number(eventTemplate?.eventTemplateId),
      }))
      const res = await apiWaybillRecordAddressInfo({ publishPathIDTOS })
      const content = form.getFieldValue('content') || []
      form.setFieldsValue({
        content: content.map((item: IFormValue['content'][number]) => {
          const addressListODTO = res?.find(resItem => resItem.waybillNo === item.waybillNo)?.addressListODTO || {}
          return {
            ...item,
            eventTemplate,
            locationType: eventTemplate?.locationType,
            statusGroup: eventTemplate?.statusGroup,
            status: eventTemplate?.status,
            ...addressListODTO,
          }
        }),
      })
    }

    const setSingleAddress = async (
      changedIndex: number,
      eventTemplate: IFormValue['content'][number]['eventTemplate'],
    ) => {
      const item = waybillList[changedIndex]
      const publishPathIDTOS = [
        {
          waybillNo: item.waybillNo,
          eventTemplateId: Number(eventTemplate?.eventTemplateId),
        },
      ]
      const res = await apiWaybillRecordAddressInfo({ publishPathIDTOS })
      const content = form.getFieldValue('content') || []
      form.setFieldsValue({
        content: content.map((item: IFormValue['content'][number]) => {
          const addressListODTO = res?.find(resItem => resItem.waybillNo === item.waybillNo)?.addressListODTO || null
          if (addressListODTO) {
            return {
              ...item,
              eventTemplate,
              locationType: eventTemplate?.locationType,
              statusGroup: eventTemplate?.statusGroup,
              status: eventTemplate?.status,
              ...addressListODTO,
            }
          } else {
            return item
          }
        }),
      })
    }

    const batchUpdateContent = (batchAction: IFormValue['batchAction']) => {
      const content = form.getFieldValue('content') || []
      const batchData = { ...batchAction }
      if ('eventTemplate' in batchAction) {
        setBatchAddress(batchAction.eventTemplate)
      }
      form.setFieldsValue({
        content: content.map((item: IFormValue['content'][number]) => ({
          ...item,
          ...batchData,
        })),
      })
    }

    const batchEvent = (changedValues: Partial<IFormValue>) => {
      if ('batchAction' in changedValues && changedValues.batchAction) {
        batchUpdateContent(changedValues.batchAction as IFormValue['batchAction'])
      }
      if ('content' in changedValues && changedValues.content) {
        const contentChanges = changedValues.content as IFormValue['content']
        if (Array.isArray(contentChanges)) {
          const changedIndex = contentChanges.findIndex(entry => entry && 'eventTemplate' in entry)
          if (changedIndex !== -1) {
            const tpl = contentChanges[changedIndex]?.eventTemplate as IFormValue['content'][number]['eventTemplate']
            if (tpl) {
              setSingleAddress(changedIndex, tpl)
            } else {
              // 模版清空时同步清空派生字段，保持 UI 值一致
              form.setFieldValue(['content', changedIndex, 'locationType'], undefined)
              form.setFieldValue(['content', changedIndex, 'statusGroup'], undefined)
              form.setFieldValue(['content', changedIndex, 'status'], undefined)
            }
          }
        }
      }
    }

    const batchUpdateTable = (changedValues: Partial<IFormValue>) => {
      if ('batchAction' in changedValues && changedValues.batchAction) {
        const content = form.getFieldValue('content') || []
        form.setFieldsValue({
          content: content.map((item: IFormValue['content'][number]) => ({
            ...item,
            ...changedValues.batchAction,
          })),
        })
      }
    }

    const firstLineChange = (changedValues: Partial<IFormValue>) => {
      if ('batchAction' in changedValues && changedValues.batchAction) {
        const {
          batchAction: { departureLocationId, destinationLocationId },
        } = changedValues
        if (departureLocationId) {
          const departureLocationName = addressList.data?.list?.find(
            item => item.addressId === departureLocationId,
          )?.chineseName
          const content = form.getFieldValue('content') || []
          form.setFieldsValue({
            content: content.map((item: IFormValue['content'][number]) => ({
              ...item,
              departureLocationName,
            })),
          })
        }
        if (destinationLocationId) {
          const destinationLocationName = addressList.data?.list?.find(
            item => item.addressId === destinationLocationId,
          )?.chineseName
          const content = form.getFieldValue('content') || []
          form.setFieldsValue({
            content: content.map((item: IFormValue['content'][number]) => ({
              ...item,
              destinationLocationName,
            })),
          })
        }
      }
      if ('content' in changedValues && changedValues.content) {
        const key = changedValues.content.findIndex(item => item)
        const { departureLocationId, destinationLocationId } = changedValues.content[key]
        if (departureLocationId) {
          const departureLocationName = addressList.data?.list?.find(
            item => item.addressId === departureLocationId,
          )?.chineseName
          form.setFieldValue(['content', key, 'departureLocationName'], departureLocationName)
        }
        if (destinationLocationId) {
          const destinationLocationName = addressList.data?.list?.find(
            item => item.addressId === destinationLocationId,
          )?.chineseName
          form.setFieldValue(['content', key, 'destinationLocationName'], destinationLocationName)
        }
      }
    }

    const tailLinesChange = (changedValues: Partial<IFormValue>) => {
      if ('batchAction' in changedValues && changedValues.batchAction) {
        const {
          batchAction: { lastMileTransportType },
        } = changedValues
        if (lastMileTransportType) {
          const lastMileCarrier = lastMileTransportType === 3 ? 'Amazon Freight' : ''
          form.setFieldValue(['batchAction', 'lastMileCarrier'], lastMileCarrier)
          const content = form.getFieldValue('content')
          form.setFieldsValue({
            content: content.map((item: IFormValue['content'][number]) => ({ ...item, lastMileCarrier })),
          })
        }
      }
      if ('content' in changedValues && changedValues.content) {
        const key = changedValues.content.findIndex(item => item)
        const { lastMileTransportType } = changedValues.content[key]
        if (lastMileTransportType) {
          const lastMileCarrier = lastMileTransportType === 3 ? 'Amazon Freight' : ''
          form.setFieldValue(['content', key, 'lastMileCarrier'], lastMileCarrier)
        }
      }
    }

    const onValuesChange = (changedValues: Partial<IFormValue>) => {
      if (operationType === 'addEventTemplate') {
        batchEvent(changedValues)
      }
      if (operationType === 'updateFirstLine') {
        firstLineChange(changedValues)
      }
      if (operationType === 'updateTailLines') {
        tailLinesChange(changedValues)
      }
      if (['updateServiceLevel', 'updateFirstLine', 'updateTailLines'].includes(operationType)) {
        batchUpdateTable(changedValues)
      }
    }

    const resultHandle = (res: IBatchSetRes) => {
      setUpdateCount(res)
      setWaybillList(
        waybillList.map(item => {
          const failReason = res.failWaybills?.find(resItem => resItem.waybillNo === item.waybillNo)?.failReason
          return {
            ...item,
            result: failReason || 1,
          }
        }),
      )
    }

    const addEventTemplate = () => {
      form
        .validateFields()
        .then(async (values: IFormValue) => {
          const { content } = values
          const publishPathIDTOS: PublishPathIDTO[] = content?.map((item: IFormValue['content'][number]) => {
            const { currentEdd, eventTime, nextUpdateTime, updateEdd, updateEddZone } = item
            return {
              ...item,
              waybillNo: item.waybillNo!,
              eventTemplateId: Number(item.eventTemplate!.eventTemplateId),
              currentEdd: currentEdd ? currentEdd!.format($F_YMD) : undefined,
              eventTime: eventTime!.format($F_YMDHms),
              nextUpdateTime: nextUpdateTime ? nextUpdateTime?.format($F_YMD) : undefined,
              updateEdd: updateEdd!.format($F_YMD),
              updateEddZone: updateEddZone!,
              nextUpdateAndEddZone: updateEddZone!,
              eventTimeZone: updateEddZone!,
              currentEddZone: updateEddZone!,
            }
          })
          const res = await apiBatchSetPublishEvent({ publishPathIDTOS })
          message.success('提交成功，查看提交结果')
          resultHandle(res)
        })
        .catch(err => {
          console.log('[91m [ 🥝  err  🥝 ]-317 [0m', err)
          message.warning('请检查表格')
        })
    }

    const updateServiceLevel = () => {
      form
        .validateFields()
        .then(async (values: IFormValue) => {
          const { content } = values
          const logisticChannelSetIDTOS: LogisticChannelSetIDTO[] = content.map(
            (row: IFormValue['content'][number]) => {
              return {
                waybillNo: row.waybillNo ?? '',
                logisticsChannelServiceLevel: Number(row.logisticsChannelServiceLevel),
                logisticsChannelServiceTransitMin: Number(row.logisticsChannelServiceTransitMin),
                logisticsChannelServiceTransitMax: Number(row.logisticsChannelServiceTransitMax),
              }
            },
          )
          const res = await apiBatchSetLogisticsChannel({ logisticChannelSetIDTOS })
          message.success('提交成功，查看提交结果')
          resultHandle(res)
        })
        .catch(err => {
          console.log('[91m [ 🥝  err  🥝 ]-317 [0m', err)
          message.warning('请检查表格')
        })
    }

    const updateFirstLine = () => {
      form
        .validateFields()
        .then(async (values: IFormValue) => {
          const { content } = values

          const firstLegInformationSetIDTOS: FirstLegInformationSetIDTO[] = (content || []).map(
            (row: IFormValue['content'][number]) => {
              return {
                waybillNo: row.waybillNo ?? '',
                carrier: row.carrier ?? '',
                vesselName: row.vesselName,
                voyageNumber: row.voyageNumber,
                containerNumber: row.containerNumber,
                departureLocationId: row.departureLocationId,
                departureLocationName: row.departureLocationName,
                destinationLocationId: row.destinationLocationId,
                destinationLocationName: row.destinationLocationName,
                transportType: row.transportType != null ? Number(row.transportType) : 1,
                etd: row.etd ? dayjs(row.etd).format($F_YMD) : undefined,
                eta: row.eta ? dayjs(row.eta).format($F_YMD) : undefined,
              }
            },
          )
          const res = await apiBatchSetFirstLegInformation({ legInformationSetIDTOS: firstLegInformationSetIDTOS })
          message.success('提交成功，查看提交结果')
          resultHandle(res)
        })
        .catch(err => {
          console.log('[91m [ 🥝  err  🥝 ]-317 [0m', err)
          message.warning('请检查表格')
        })
    }

    const updateTailLines = () => {
      form
        .validateFields()
        .then(async (values: IFormValue) => {
          const { content } = values
          const lastMileSetIDTOS: LastMileSetIDTO[] = content.map((row: IFormValue['content'][number]) => {
            return {
              waybillNo: row.waybillNo ?? '',
              lastMileCarrier: row.lastMileCarrier ?? '',
              lastMileTransportType: row.lastMileTransportType as number | undefined,
              lastMileWaybillNo: row.lastMileWaybillNo ?? '',
            }
          })
          const res = await apiBatchSetLastLegInformation({ lastMileSetIDTOS })
          message.success('提交成功，查看提交结果')
          resultHandle(res)
        })
        .catch(err => {
          console.log('[91m [ 🥝  err  🥝 ]-317 [0m', err)
          message.warning('请检查表格')
        })
    }

    const handleSuccess = () => {
      if (operationType === 'addEventTemplate') {
        addEventTemplate()
      }
      if (operationType === 'updateServiceLevel') {
        updateServiceLevel()
      }
      if (operationType === 'updateFirstLine') {
        updateFirstLine()
      }
      if (operationType === 'updateTailLines') {
        updateTailLines()
      }
    }

    useEffect(() => {
      if (open) {
        initForm()
        getEventList()
      }
    }, [open])

    return (
      <Drawer
        className={styles.drawer}
        title={operationTypeTitleMap[operationType]}
        width={1200}
        open={open}
        onClose={onHide}
        afterOpenChange={afterOpenChange}
        destroyOnClose
        footer={
          <div className={styles.footer}>
            <div>
              总计: {waybillList.length} 成功:{' '}
              <Typography.Text type="success" strong>
                {updateCount?.successTotal || 0}
              </Typography.Text>{' '}
              失败:{' '}
              <Typography.Text type="danger" strong>
                {updateCount?.failTotal || 0}
              </Typography.Text>
            </div>
            <Space>
              <Button onClick={() => form.resetFields()}>清空</Button>
              <Button onClick={onHide}>取消</Button>
              <Button type="primary" onClick={handleSuccess}>
                确认更新
              </Button>
            </Space>
          </div>
        }
      >
        <div className={styles.drawer_body}>
          <Form form={form} layout="vertical" onValuesChange={onValuesChange}>
            <BatchAction operationType={operationType} addressList={addressList} />
            {operationType === 'addEventTemplate' ? (
              <AddEvent />
            ) : (
              <BatchUpdateTable operationType={operationType} addressList={addressList} />
            )}
          </Form>
        </div>
      </Drawer>
    )
  },
  {
    open: (params: IBatchOperationsDrawerProps) => {
      updatePopup(<BatchOperationsDrawer {...params} destroy={() => updatePopup(null)} />)
    },
  },
)
